package main

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"
	"unsafe"
)

/*
	块注释
*/
func main2() { //程序的入口
	// fmt.Println("hello world")
	// fmt.Println("hello world")
	// fmt.Println("hello world")
	// fmt.Println("sd")

	// var_fun()// 变量
	// data_type()//数据类型
	// poitor() // 指针

	// input1()
	// input2()

	// ifelse()
	// testSwith()

	// testFor()
	//fmt.Println(utils.Cal(1, 2, "+"))

	//testFunc()

	//makeJpgSuffix := makeSuffix("jpg")
	//fmt.Println("文件名：", makeJpgSuffix("1"))
	//fmt.Println("文件名：", makeJpgSuffix("2"))

	//testDefer()

	//testString()

	//testTime()

	//testError()
	testError2()
}

func var_fun() {
	var num int
	num = 1
	fmt.Println("num=", num)

	num2 := 10 //省略var
	fmt.Println("num2=", num2)

	num3, num4 := 12, 12.5     //一次声明多个变量
	var num5, num6 = 22, "123" //一次声明多个变量
	fmt.Println("num3=", num3, ",num4=", num4)
	fmt.Println("num5=", num5, ",num6=", num6)

	var (
		num7 = 12
		num8 = 12.4
	)
	fmt.Println("num7=", num7, ",num8=", num8)

	fmt.Println("全局变量goable_num1=", goable_num1)
}

var goable_num1 = 10 // 全局变量

func data_type() {
	var num = 10
	fmt.Printf("num的类型 %T, 占用的字节大小 %d \n", num, unsafe.Sizeof(num))

	var num_str = fmt.Sprintf("%d", num)
	fmt.Println("num_str=", num_str)
	var num_str1 = strconv.FormatInt(int64(num), 10)
	var num_str2 = strconv.Itoa(num)
	fmt.Println("num_str1=", num_str1)
	fmt.Println("num_str2=", num_str2)

	num2, _ := strconv.ParseInt("123", 10, 64)
	fmt.Println("解析后数字", num2)
}

func poitor() {
	var num int
	num = 10
	fmt.Println("num变量的地址", &num)

	//定义一个指针，指向num变量
	var p *int = &num
	fmt.Println("通过指针获取变量的值", *p)

	//通过指针修改变量的值
	*p = 20
	fmt.Println("通过指针获取变量的值", *p)
}

func input1() {
	// 方式一，使用Scanln
	var name string
	var age byte
	var sal float32
	var isPass bool

	fmt.Println("请输入姓名")
	fmt.Scanln(&name)
	fmt.Println("请输入年龄")
	fmt.Scanln(&age)
	fmt.Println("请输入薪水")
	fmt.Scanln(&sal)
	fmt.Println("请输入是否通过考试")
	fmt.Scanln(&isPass)
	// 1. %v    只输出所有的值
	// 2. %+v 先输出字段类型，再输出该字段的值
	// 3. %#v 先输出结构体名字值，再输出结构体（字段类型+字段的值）

	fmt.Printf("姓名：%v; 年龄：%v; 薪水：%v; 是否通过考试：%v \n", name, age, sal, isPass)

}

func ifelse() {
	if age := 12; age < 18 {
		fmt.Println("未成年")
	}
}

func testSwith() {
	y := 10
	var x interface{}
	x = y
	switch x.(type) {
	case nil:
		fmt.Println("null类型")
	case int:
		fmt.Println("int类型")
	case float64:
		fmt.Println("double类型")
	default:
		fmt.Println("unknown")
	}
}

func input2() {
	// 方式二，使用Scanf
	var name string
	var age byte
	var sal float32
	var isPass bool
	fmt.Println("请输入姓名,年龄，薪水，是否通过考试 4个信息，信息之间用空格分隔")
	fmt.Scanf("%s %d %f %t", &name, &age, &sal, &isPass)
	fmt.Printf("姓名：%v; 年龄：%v; 薪水：%v; 是否通过考试：%v \n", name, age, sal, isPass)
}

func testFor() {
	str := "你好啊"
	for index, val := range str {
		fmt.Printf("index=%d, val=%c \n", index, val)
	}

	i := 0

lable:
	for {
		for {
			fmt.Println("循环了", i, "次")
			i++
			if i > 10 {
				break lable
			}
		}
	}

lable2:
	for i := 0; i < 5; i++ {
		for j := 0; j < 5; j++ {
			if j == 2 {
				continue lable2
			}
			fmt.Println("循环i=", i, ";j=", j)
		}
	}
}

func testError2() {
	res, _ := readConf("config.ini")
	println("res=", res)
	res2, err2 := readConf("config.in")
	if err2 != nil {
		println("发生异常", err2.Error())
	} else {
		println("res2=", res2)
	}
}

func readConf(name string) (res string, err error) {
	if name == "config.ini" {
		return "success", nil
	} else {
		return "", errors.New("读取配置文件出错")
	}
}

func testError() {
	defer func() {
		err := recover()
		if err != nil {
			println("捕获到异常", err)
		}
	}()

	n1 := 10
	n2 := 0
	res := n1 / n2
	println("res=", res)
}

func testTime() {
	now := time.Now()
	fmt.Println(now) //2022-12-04 20:22:03.056697 +0800 CST m=+0.000172713
	year := now.Year()
	fmt.Println(year)                  //2022
	fmt.Printf("%v %T \n", year, year) //2022 int

	format := now.Format("2006-01")
	println(format) //2022-12

	println(now.Unix()) //秒
	println(now.UnixMilli())
	println(now.UnixMicro())
	println(now.UnixNano())

	start := time.Now().UnixMilli()
	time.Sleep(time.Millisecond * 1000)
	cost := time.Now().UnixMilli() - start
	println("休眠结束,耗时：", cost)
}

// 测试字符串的函数
func testString() {
	str := "字符串"
	fmt.Println("字符串长度", len(str)) // 9
	str = "hello中国"
	r := []rune(str)
	for i := 0; i < len(r); i++ {
		fmt.Printf("遍历字符串：%c\n", r[i])
	}
	r2 := []int32(str)
	for i := 0; i < len(r2); i++ {
		fmt.Printf("遍历字符串：%c\n", r2[i])
	}
	//字符串转整数
	num, err := strconv.Atoi("124hello")
	if err != nil {
		fmt.Println("转换错误，err：", err)
	} else {
		fmt.Println("转换成功，num：", num)
	}
	num2, err2 := strconv.ParseInt("123", 10, 64)
	if err2 != nil {
		fmt.Println("转换错误，err2：", err2)
	} else {
		fmt.Println("转换成功，num2：", num2)
	}

	//整数转字符串
	str = strconv.Itoa(123)
	fmt.Println("整数转字符串", str)
}

func testDefer() {
	defer fmt.Println("defer压入栈，1")
	defer fmt.Println("defer压入栈，2")
	fmt.Println("整成执行，3")
}

func makeSuffix(suffix string) func(string) string {
	return func(name string) string {
		if !strings.HasPrefix(name, suffix) {
			return name + "." + suffix
		}
		return name
	}
}

var globalSum = func(n1 int, n2 int) int {
	return n1 + n2
}

func testFunc() {
	res1 := func(n1 int, n2 int) int {
		return n1 + n2
	}(10, 20)
	fmt.Println("定时匿名函数时直接使用，res1=", res1)

	res2 := func(n1 int, n2 int) int {
		return n1 + n2
	}
	fmt.Println("匿名函数赋值给变量调用，res2=", res2(10, 20))

	fmt.Println("匿名函数赋值给全局变量调用，res3=", globalSum(10, 20))
}
